/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-07-23     Administrator       the first version
 * 2022-05-20     wyj          1.0.9修改了延时无人判断的bug
 */

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

#include "pcf8574.h"
#include "IO/io.h"
#define DBG_TAG "io"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

#define TEST_IO    0 //(0-7)
#define I2C_BUS    "i2c2"

static pcf8574_device_t io_dev = RT_NULL;
static io_status_s io_status; 

rt_mutex_t get_io_mutex = RT_NULL;
int io_init(void)
{
    rt_pin_mode(RELAY0_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(RELAY1_PIN, PIN_MODE_OUTPUT);
    rt_pin_write(RELAY0_PIN, DEV_RELAY_OFF);
    rt_pin_write(RELAY1_PIN, DEV_RELAY_OFF);
    io_dev = pcf8574_init(I2C_BUS, PCF8574_ADDR);

    if (io_dev == RT_NULL)
    {
        LOG_E("io init failed!!");
        return -1;
    }
    get_io_mutex = rt_mutex_create("get io dmutex", RT_IPC_FLAG_FIFO);
    if (get_io_mutex == RT_NULL)
    {
        LOG_E("create get io dmutex mutex failed.\n");
        return -1;
    }
//    value = pcf8574_pin_read(dev, RELAY0_STATUS);
//    rt_kprintf("The value of pcf8574.P%d is %d\n", RELAY0_STATUS, value);
//    value = pcf8574_pin_read(dev, RELAY1_STATUS);
//    rt_kprintf("The value of pcf8574.P%d is %d\n", RELAY1_STATUS, value);
//
//    rt_thread_mdelay(1000);
//    rt_pin_write(RELAY0_PIN, 1);
//    rt_thread_mdelay(500);
//    value = pcf8574_pin_read(dev, RELAY0_STATUS);
//    rt_kprintf("The value of pcf8574.P%d is %d\n", RELAY0_STATUS, value);
//
//    rt_pin_write(RELAY1_PIN, 1);
//    rt_thread_mdelay(500);
//    value = pcf8574_pin_read(dev, RELAY1_STATUS);
//    rt_kprintf("The value of pcf8574.P%d is %d\n", RELAY1_STATUS, value);

    return 0;
}
////input  :relayx   :RELAY0  or RELAY1
///         status   :RELAY_ON or RELAY_OFF

void set_io_status(uint8_t relayx,uint8_t status)
{
    rt_pin_write(relayx, status);
}
static void change_relay(void)
{
    static uint8_t relay_io_value = 0;
    if (relay_io_value)
    {
        rt_pin_write(RELAY0_PIN, 0);
        rt_pin_write(RELAY1_PIN, 0);
        relay_io_value = 0;
    }
    else
    {
        rt_pin_write(RELAY0_PIN, 1);
        rt_pin_write(RELAY1_PIN, 1);
        relay_io_value = 1;
    }
}
MSH_CMD_EXPORT(change_relay, change relay);
rt_uint8_t get_io_status(uint8_t IO_PIN)
{
    rt_uint8_t io_value;
    rt_mutex_take(get_io_mutex, RT_WAITING_FOREVER);

    io_value = pcf8574_pin_read(io_dev, IO_PIN);

    rt_mutex_release(get_io_mutex);
    return io_value;
}

// 获取所有状态
static struct io_status_s io_get_all_status() 
{
    struct io_status_s status;
    // 红外
    if (get_io_status(INFRARED_STATUS) == ANYBODY_PIN_STATUS) {
        status.infrared = DEV_INFRARED_ANYBODY;
    } else {
        status.infrared = DEV_INFRARED_NOBODY;
    }
    // 门禁
    if (get_io_status(DOOR_STATUS) == DOOR_OPEN_PIN_STATUS) {
        status.door = DEV_DOOR_OPEN;
    } else{
        status.door = DEV_DOOR_CLOSE;
    }
    // 继电器0
    if (get_io_status(RELAY0_STATUS) == 0) {
        status.relay0 = DEV_RELAY_ON;
    } else{
        status.relay0 = DEV_RELAY_OFF;
    }
    // 继电器1
    if (get_io_status(RELAY1_STATUS) == 0) {
        status.relay1 = DEV_RELAY_ON;
    } else{
        status.relay1 = DEV_RELAY_OFF;
    }
    // 按键0
    if (get_io_status(KEY0_STATUS) == 0) {
        status.key0 = DEV_KEY_PRESS;
    } else{
        status.key0 = DEV_KEY_RELEASE;
    }
    // 按键1
    if (get_io_status(KEY1_STATUS) == 0) {
        status.key1 = DEV_KEY_PRESS;
    } else{
        status.key1 = DEV_KEY_RELEASE;
    }
    // 按键2
    if (get_io_status(KEY2_STATUS) == 0) {
        status.key2 = DEV_KEY_PRESS;
    } else{
        status.key2 = DEV_KEY_RELEASE;
    }
    // 按键3
    if (get_io_status(KEY3_STATUS) == 0) {
        status.key3 = DEV_KEY_PRESS;
    } else{
        status.key3 = DEV_KEY_RELEASE;
    }
    // 连锁状态判断
    if (status.infrared == DEV_INFRARED_ANYBODY || status.door == DEV_DOOR_OPEN) {
        status.chain = DEV_CHAIN_ERROR;
    } else{
        status.chain = DEV_CHAIN_OK;
    }

    return status;
}

void io_check_once() {
    struct io_status_s status;
    status = io_get_all_status();
    io_upload_callback(&status);
} 

static void io_check_loop() 
{
    int upload_run = 0;
    int chain_run = 0;
    struct io_status_s s;

    // 获取当前io口状态
    s = io_get_all_status();

    // 更新状态
    if (s.key0 != io_status.key0) {
        io_status.key0 = s.key0;
        upload_run = 1; // 状态变化，上传
    }
    if (s.key1 != io_status.key1) {
        io_status.key1 = s.key1;
        upload_run = 1;
    }
    if (s.key2 != io_status.key2) {
        io_status.key2 = s.key2;
        upload_run = 1;
    }
    if (s.key3 != io_status.key3) {
        io_status.key3 = s.key3;
        upload_run = 1;
    }
    if (s.relay0 != io_status.relay0) {
        io_status.relay0 = s.relay0; 
        upload_run = 1;
    }
    if (s.relay1 != io_status.relay1) {
        io_status.relay1 = s.relay1;
        upload_run = 1;
    }
    if (s.door != io_status.door) {
        io_status.door = s.door;
        chain_run = 1; // 门禁变化，检测连锁
        upload_run = 1;
    }
    // 红外检测, 无人时进行超时检测
    if (s.infrared != io_status.infrared) { 

        chain_run = 1; // 红外变化，检测连锁
        if (s.infrared == DEV_INFRARED_ANYBODY) // 有人时开启上传
        {
            io_status.infrared = s.infrared;                //有人时立刻赋值
            if (!_nobody_flag) {
                LOG_I("Infrared Anybody!!!\r\n");
                upload_run = 1;
                io_status.infrared = s.infrared;
            }
        }
        // 无人的时候延时后再检测一次
        if ((s.infrared == DEV_INFRARED_NOBODY)&&(_nobody_flag == 0)) {
            LOG_I("Infrared Nobody Timeout Check Start...\r\n");
            // 清空超时,开启无人超时检测
            _nobody_flag = 1;
            _nobody_cnt = 0;
        }  
    }
    // 无人超时检测时间到, 超时检测，确认无人
    if (_nobody_flag) {
        // 超时
        if ((_nobody_cnt * IO_CHECK_PERIOD / 1000) >= INFRARED_NOBODY_TIMEOUT ) {
            LOG_I("Infrared Nobody Timeout :%d\r\n", _nobody_cnt);
            _nobody_cnt = 0; // 清空超时
            if (s.infrared == DEV_INFRARED_NOBODY) {
                // 确认无人, 上传状态，关闭检测，
                _nobody_flag = 0;
                upload_run = 1; // 上传状态
                chain_run = 1; // 红外变化，检测连锁
                io_status.infrared = s.infrared;                //有人变无人延时确认后赋值
            }  
        } 
        _nobody_cnt += 1;
    }

    // 自动化连锁控制
    // 情况1： 红外有人 || 门开   ->   关闭源控
    if (chain_run) {
        if (io_status.infrared == DEV_INFRARED_ANYBODY || io_status.door == DEV_DOOR_OPEN) {
            io_status.chain = DEV_CHAIN_ERROR; // 禁止出源
            set_io_status(RELAY0, DEV_RELAY_OFF); // 关闭继电器
            set_io_status(RELAY1, DEV_RELAY_OFF); // 关闭继电器
        } else{
            io_status.chain = DEV_CHAIN_OK; // 允许出源
            set_io_status(RELAY0, DEV_RELAY_ON); // 开启继电器
            set_io_status(RELAY1, DEV_RELAY_ON); // 开启继电器
        }
    }

    // 上传状态
    if (upload_run) {
        io_upload_callback(&io_status);
    }
    
}

// static void io_check_loop() 
// {
//     int upload_flag = 0;
//     struct io_status_s s;

//     s = io_get_all_status();


//     // 自动化连锁控制
//     // 情况1： 红外有人 || 门开   ->   关闭源控
//     // 状态发生变化，执行连锁动作，上传状态

//     if (s.infrared != io_status.infrared || s.door != io_status.door) {
//         // 红外有人 || 门禁开启
//         if (s.infrared == DEV_INFRARED_ANYBODY || s.door == DEV_DOOR_OPEN) {
//             set_io_status(RELAY0, DEV_RELAY_OFF); // 关闭继电器
//             set_io_status(RELAY1, DEV_RELAY_OFF); // 关闭继电器
//         } else{
//             set_io_status(RELAY0, DEV_RELAY_ON); // 开启继电器
//             set_io_status(RELAY1, DEV_RELAY_ON); // 开启继电器
//         }
//     }
//     if (s.key0 != io_status.key0 ||
//         s.key1 != io_status.key1 ||
//         s.key2 != io_status.key2 ||
//         s.key3 != io_status.key3 ||
//         s.relay0 != io_status.relay0 ||
//         s.relay1 != io_status.relay1 ||
//         s.infrared != io_status.infrared ||
//         s.door != io_status.door ||
//         s.chain != io_status.chain)
//     {
//         // 更新并上传状态
//         io_status = io_get_all_status(); //更新状态
//         io_upload_callback(&io_status);
//     }
// }


// 自动控制连锁
void io_check_thread(void* paramenter)
{
    while (1)
    {
        io_check_loop();
        rt_thread_mdelay(IO_CHECK_PERIOD);
    }
}
// 开启连锁线程
void io_check_start() {
    // 开启检测线程
    rt_thread_t tid = RT_NULL;
    // rt_err_t result;
    tid = rt_thread_create("io_check", io_check_thread, RT_NULL, 1024, RT_THREAD_PRIORITY_MAX / 2, 2);
    if (tid != RT_NULL)
    {
        rt_thread_startup(tid);
    }
}

INIT_APP_EXPORT(io_init);
